package com.cloud.picture.controller;

import com.cloud.picture.annotation.AuthCheck;
import com.cloud.picture.common.BaseResponse;
import com.cloud.picture.constant.UserConstants;
import com.cloud.picture.exception.BusinessException;
import com.cloud.picture.manager.CosManager;
import com.cloud.picture.model.enums.ErrorCodeEnum;
import com.cloud.picture.model.vo.UserVO;
import com.cloud.picture.service.UserService;
import com.cloud.picture.utils.ResultUtils;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.COSObjectInputStream;
import com.qcloud.cos.utils.IOUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * @author syf
 */

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
    @Resource
    private UserService userService;

    @Resource
    private CosManager cosManager;

    /**
     * 健康检测
     */
    @RequestMapping("/health")
    public BaseResponse<String> health() {
        return ResultUtils.success("ok");
    }

    @PostMapping("/upload")
    public BaseResponse<String> testUploadFile(@RequestPart("file") MultipartFile multipartFile) {

        // 文件目录
        String filename = multipartFile.getOriginalFilename();
        if (filename == null) {
            throw new BusinessException(ErrorCodeEnum.PARAMS_ERROR);
        }
        String filepath = String.format("/test/%s", filename);
        File file = null;
        try {
            // 上传文件
            file = File.createTempFile(filename, null);
            multipartFile.transferTo(file);
            cosManager.putObject(filepath, file);
            // 返回可访问地址
            return ResultUtils.success(filepath);
        } catch (Exception e) {
            log.error("file upload error, filepath = {}", filepath, e);
            throw new BusinessException(ErrorCodeEnum.SYSTEM_ERROR, "上传失败");
        } finally {
            if (file != null) {
                // 删除临时文件
                boolean delete = file.delete();
                if (!delete) {
                    log.error("file delete error, filepath = {}", filepath);
                }
            }
        }

    }

    @PostMapping("/sendEmail")
    public BaseResponse<String> sendEmail(String email) {
        String code = userService.sendEmail(email);
        return ResultUtils.success(code);
    }

    @PostMapping("/getListVo")
    public BaseResponse<List<UserVO>> getUserVoList() {
        List<UserVO> userVOList = userService.getUserVOList(null);
        return ResultUtils.success(userVOList);
    }

    @AuthCheck(mustRole = UserConstants.ADMIN_ROLE)
    @GetMapping("/download")
    public void testDownloadFile(String filepath, HttpServletResponse response) throws IOException {
        COSObjectInputStream cosObjectInput = null;
        try {
            COSObject cosObject = cosManager.getObject(filepath);
            cosObjectInput = cosObject.getObjectContent();
            byte[] bytes = IOUtils.toByteArray(cosObjectInput);
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename="+filepath);
            response.getOutputStream().write(bytes);
            response.getOutputStream().flush();
        } catch (IOException e) {
            throw new BusinessException(ErrorCodeEnum.SYSTEM_ERROR, "下载失败");
        } finally {
            if (cosObjectInput != null) {
                cosObjectInput.close();
            }
        }
    }

    @PostMapping("/npv")
    public BaseResponse<Double> getNPV(double [] cashFlows, double discountRate) {
        double npv = calculateNPV(cashFlows, discountRate);
        return ResultUtils.success(npv);
    }

    @PostMapping("/irr")
    public BaseResponse<Double> getIRR(double [] cashFlows) {
        double irr = calculateIrr(cashFlows);
        return ResultUtils.success(irr);
    }

    @PostMapping("/payback")
    public BaseResponse<Double> getPaybackPeriod(double [] cashFlows) {
        double paybackPeriod = calculatePaybackPeriod(cashFlows);
        return ResultUtils.success(paybackPeriod);
    }

    private double calculateNPV(double[] cashFlows, double discountRate) {
        double npv = 0;
        for (int t = 0; t < cashFlows.length; t++) {
            npv += cashFlows[t] / Math.pow(1 + discountRate, t);
        }
        return npv;
    }

    private double calculateIrr(double[] cashFlows) {
        // 初始猜测值
        double irr = 0.1;
        double precision = 0.0001;
        for (int i = 0; i < 100; i++) {
            double npv = calculateNPV(cashFlows, irr);
            if (Math.abs(npv) < precision) break;
            // 计算导数近似值
            double npvDerivative = (calculateNPV(cashFlows, irr + 0.0001) - npv) / 0.0001;
            irr -= npv / npvDerivative;
        }
        return irr;
    }
    private double calculatePaybackPeriod(double[] cashFlows) {
        double cumulative = 0;
        for (int t = 0; t < cashFlows.length; t++) {
            cumulative += cashFlows[t];
            if (cumulative >= 0) {
                // 线性插值计算部分年
                return t - 1 + (-cumulative + cashFlows[t]) / cashFlows[t];
            }
        }
        // 未收回
        return -1;
    }
}
